const API = "";
let currentPid = 0, parentStack = [], editingId = null, deletingId = null;
let currentFileInfo = { // 存储当前文件信息
    name: "",
    size: 0,
    base64: "",
    uploadTime: "",
    metadataError: false
};
/* 缓存所有节点的文件信息，方便直接下载
    * 20250907(qing): 文件多了会卡 */
let nodeFileCache = {};

// 缓存DOM元素引用，不用每次都去找
const domElements = {
    deleteModal: null,
    deleteMessage: null,
    deleteNodeTitle: null,
    deleteFileHint: null,
    toastContainer: null,
    fileInfo: null,
    fileMetaContainer: null,
    fileMetaInfo: null,
    metaFilename: null,
    metaFilesize: null,
    metaUploadtime: null,
    fileProgress: null,
    fileProgressBar: null,
    fileUpload: null,
    hiddenBase64: null,
    fileMetadata: null,
    downloadSection: null,
    dataRepairHint: null
};

// 初始化DOM元素引用
function initDomElements() {
    domElements.deleteModal = document.getElementById("delete-modal");
    domElements.deleteMessage = document.getElementById("delete-message");
    domElements.deleteNodeTitle = document.getElementById("delete-node-title-container");
    domElements.deleteFileHint = document.getElementById("delete-file-hint");
    domElements.toastContainer = document.getElementById("toast-container");
    domElements.fileInfo = document.getElementById("file-info");
    domElements.fileMetaContainer = document.getElementById("file-meta-container");
    domElements.fileMetaInfo = document.getElementById("file-meta-info");
    domElements.metaFilename = document.getElementById("meta-filename");
    domElements.metaFilesize = document.getElementById("meta-filesize");
    domElements.metaUploadtime = document.getElementById("meta-uploadtime");
    domElements.fileProgress = document.querySelector(".file-progress");
    domElements.fileProgressBar = document.getElementById("file-progress-bar");
    domElements.fileUpload = document.getElementById("file-upload");
    domElements.hiddenBase64 = document.getElementById("hidden-base64");
    domElements.fileMetadata = document.getElementById("file-metadata");
    domElements.downloadSection = document.getElementById("download-section");
    domElements.dataRepairHint = document.getElementById("data-repair-hint");
    
    // 验证关键元素是否存在
    const missingElements = [];
    for (const [key, element] of Object.entries(domElements)) {
    if (!element) {
        missingElements.push(key);
    }
    }
    
    if (missingElements.length > 0) {
    console.error("关键DOM元素缺失:", missingElements);
    alert("系统初始化失败，关键组件缺失，请刷新页面重试。");
    }
}

// 提示消息
function showToast(msg, type = 'info') {
    if (!domElements.toastContainer) {
    console.error("toast容器未找到，无法显示提示");
    return;
    }
    
    const t = document.createElement('div');
    t.className = `toast ${type} show`;
    t.innerHTML = `<i class="fas fa-${type === 'success' ? 'check' : type === 'error' ? 'exclamation-triangle' : type === 'warning' ? 'exclamation-circle' : 'info-circle'}"></i> ${msg}`;
    domElements.toastContainer.appendChild(t);
    setTimeout(() => t.remove(), 3000); // 3秒后删除
}

// HTML转义字符还原
// 我在编辑节点时，转义符号没有能够被替换
function htmlUnescape(str) {
    if (!str || typeof str !== 'string') {
    return str;
    }
    return str
    .replace(/&amp;/g, '&')
    .replace(/&lt;/g, '<')
    .replace(/&gt;/g, '>')
    .replace(/&quot;/g, '"')
    .replace(/&#039;/g, "'")
    .replace(/&#x60;/g, '`');
}
//-----
// 安全的JSON解析函数 - 新增HTML转义还原处理
function safeJsonParse(jsonString, defaultValue = {}) {
    try {
    // 先进行HTML转义还原
    const unescapedString = htmlUnescape(jsonString);
    
    // 再进行基本的格式检查
    if (!unescapedString || typeof unescapedString !== 'string' || 
        unescapedString.trim() === '' || 
        !unescapedString.startsWith('{') || !unescapedString.endsWith('}')) {
        console.error('无效的JSON格式：不是有效的对象字符串');
        return defaultValue;
    }
    
    return JSON.parse(unescapedString);
    } catch (e) {
    console.error('JSON解析失败:', e);
    console.error('问题数据:', jsonString);
    
    // 尝试提取可能有用的信息
    try {
        // 先进行HTML转义还原，再清理可能导致错误的字符
        const cleanedString = htmlUnescape(jsonString).replace(/[^\x20-\x7E]/g, '');
        if (cleanedString !== jsonString) {
        console.log('尝试清理无效字符后重新解析');
        return JSON.parse(cleanedString);
        }
    } catch (cleanError) {
        console.error('清理后仍无法解析:', cleanError);
    }
    
    return defaultValue;
    }
}

// 安全的JSON字符串化函数
function safeJsonStringify(data) {
    try {
    return JSON.stringify(data);
    } catch (e) {
    console.error('JSON序列化失败:', e);
    // 尝试使用更宽松的序列化方式
    try {
        return JSON.stringify(data, (key, value) => {
        if (typeof value === 'bigint') {
            return value.toString();
        }
        return value;
        });
    } catch (fallbackError) {
        console.error('备用序列化方式也失败:', fallbackError);
        return '{}'; // 返回空对象作为最后的 fallback
    }
    }
}

// API请求
async function request(endpoint, data = {}) {
    try {
    const res = await fetch(API + endpoint, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(data)
    });
    return res.ok ? await res.json() : Promise.reject(res.status);
    } catch (e) {
    showToast(`请求失败: ${e}`, 'error');
    throw e;
    }
}

// 检查节点是否有子节点
async function hasChildren(nodeId) {
    try {
    const children = await request("/get_notes", { pid: nodeId });
    return Array.isArray(children) && children.length > 0;
    } catch (e) {
    showToast("检查子节点失败", 'error');
    return false;
    }
}

// 解析节点内容，分离说明文本和文件信息
function parseNodeContent(content) {
    try {
    // 检查内容是否包含文件信息标记
    if (content.startsWith('FILE_METADATA:')) {
        const parts = content.split('\n---\n');
        if (parts.length >= 3) {
        const metaStr = parts[1] || '{}'; // 确保有默认值
        const base64 = parts[2] || '';
        const textContent = parts.slice(3).join('\n---\n');
        
        // 使用安全的JSON解析函数，已包含HTML转义还原
        const meta = safeJsonParse(metaStr, {
            name: '未知文件',
            size: 0,
            uploadTime: '未知时间'
        });
        
        // 检查解析结果是否有效
        const isValidMeta = meta && typeof meta === 'object' && 
                            typeof meta.name === 'string' && 
                            !isNaN(meta.size);
                            
        if (!isValidMeta) {
            console.error('解析的元数据无效，使用默认值');
            return {
            hasFile: true,
            text: textContent,
            meta: {
                name: '损坏的文件',
                size: 0,
                uploadTime: '未知时间'
            },
            base64: base64,
            metadataError: true // 标记元数据解析错误
            };
        }
        
        return {
            hasFile: true,
            text: textContent,
            meta: meta,
            base64: base64,
            metadataError: false
        };
        }
    }
    
    // 普通文本内容
    return {
        hasFile: false,
        text: content,
        meta: null,
        base64: '',
        metadataError: false
    };
    } catch (e) {
    console.error('解析节点内容失败:', e);
    showToast('节点内容解析失败，可能是格式错误', 'error');
    return {
        hasFile: false,
        text: content || '解析失败的内容',
        meta: null,
        base64: '',
        metadataError: false
    };
    }
}

// 渲染节点列表（不在页面显示Base64内容）
function renderNodes(nodes) {
    const container = document.getElementById("node-list");
    if (!container) {
    console.error("节点列表容器未找到");
    return;
    }
    
    // 清空缓存
    nodeFileCache = {};
    
    if (!nodes || !nodes.length) {
    container.innerHTML = `<div class="empty-state"><i class="fas fa-folder-open"></i><p>目录为空</p><p>使用上方表单添加新节点</p></div>`;
    return;
    }

    container.innerHTML = nodes.map(n => {
    // 解析节点内容，分离文本和文件信息
    const parsed = parseNodeContent(n.content);
    const safeTitle = encodeURIComponent(escapeHtml(n.title));
    const safeContent = encodeURIComponent(escapeHtml(n.content));
    const displayTitle = escapeHtml(n.title);
    const deleteBtnId = `delete-btn-${n.id}`;
    
    // 缓存文件信息，用于直接下载
    if (parsed.hasFile) {
        nodeFileCache[n.id] = {
        name: parsed.meta.name,
        base64: parsed.base64,
        metadataError: parsed.metadataError
        };
    }
    
    // 节点内容显示文本说明，不显示Base64
    const contentDisplay = parsed.text 
        ? `<div class="node-content">${escapeHtml(parsed.text)}</div>`
        : '';
        
    // 文件错误提示
    const fileErrorIndicator = parsed.metadataError 
        ? `<div style="color: #e74c3c; font-size: 0.8em; margin-top: 5px;">
            <i class="fas fa-exclamation-circle"></i> 文件信息损坏，建议重新上传
            </div>`
        : '';
        
    // 文件指示器和下载按钮
    const fileIndicator = parsed.hasFile 
        ? `<div class="file-indicator">
            <i class="fas fa-file"></i> 包含文件: ${escapeHtml(parsed.meta.name)} (${formatFileSize(parsed.meta.size)})
            <button class="download-btn" onclick="decodeAndDownload(${n.id}, '${escapeHtml(parsed.meta.name)}')">
                <i class="fas fa-download"></i> 下载
            </button>
            </div>
            ${fileErrorIndicator}`
        : '';
    
    return `
        <div class="node ${parsed.hasFile ? 'has-file' : ''}">
        <div class="node-title" onclick="enterNode(${n.id})">
            <i class="fas ${parsed.hasFile ? 'fa-file' : 'fa-folder'}"></i> ${displayTitle}
        </div>
        ${contentDisplay}
        ${fileIndicator}
        <div class="node-actions">
            <button onclick="editNode(${n.id}, '${safeTitle}', '${safeContent}')" class="btn btn-warning"><i class="fas fa-edit"></i> 编辑</button>
            <button id="${deleteBtnId}" onclick="checkAndShowDeleteModal(event, ${n.id}, '${displayTitle}', ${parsed.hasFile})" class="btn btn-danger"><i class="fas fa-trash"></i> 删除</button>
        </div>
        </div>
    `;
    }).join('');
}

// HTML转义
function escapeHtml(unsafe) {
    if (!unsafe) return '';
    return unsafe
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#039;")
    .replace(/`/g, "&#x60;");
}

// 加载节点
async function load(pid = 0) {
    try {
    const numericPid = Number(pid);
    if (isNaN(numericPid)) {
        throw new Error("无效的节点ID");
    }
    
    const nodes = await request("/get_notes", { pid: numericPid });
    if (Array.isArray(nodes)) {
        renderNodes(nodes);
    } else {
        throw new Error("返回数据格式不正确");
    }
    } catch (e) {
    showToast(`加载失败: ${e.message}`, 'error');
    console.error("加载节点错误:", e);
    }
}

// 进入节点
function enterNode(id) {
    const numericId = Number(id);
    if (isNaN(numericId)) {
    showToast("无效的节点ID", 'error');
    return;
    }
    
    parentStack.push(currentPid);
    currentPid = numericId;
    resetForm();
    load(currentPid);
    showToast(`进入节点 ${numericId}`, 'info');
}

// 返回上级
function goBack() {
    if (parentStack.length) {
    currentPid = parentStack.pop();
    resetForm();
    load(currentPid);
    showToast('返回上级', 'info');
    } else {
    showToast('已是顶级目录', 'info');
    }
}

// 重置表单
function resetForm() {
    const editIdEl = document.getElementById("edit-id");
    const nodeTitleEl = document.getElementById("node-title");
    const nodeContentEl = document.getElementById("node-content");
    const formModeTextEl = document.getElementById("form-mode-text");
    
    if (editIdEl && nodeTitleEl && nodeContentEl && formModeTextEl) {
    editIdEl.value = "";
    nodeTitleEl.value = "";
    nodeContentEl.value = "";
    formModeTextEl.textContent = "新增节点";
    nodeTitleEl.focus();
    editingId = null;
    
    // 重置文件相关字段
    currentFileInfo = { name: "", size: 0, base64: "", uploadTime: "", metadataError: false };
    
    if (domElements.fileUpload) domElements.fileUpload.value = "";
    if (domElements.fileInfo) domElements.fileInfo.textContent = "未选择文件";
    if (domElements.fileMetaContainer) domElements.fileMetaContainer.style.display = "none";
    if (domElements.fileMetaInfo) {
        domElements.fileMetaInfo.className = "file-meta-info"; // 重置样式
    }
    if (domElements.dataRepairHint) domElements.dataRepairHint.style.display = "none";
    if (domElements.fileProgress) domElements.fileProgress.style.display = "none";
    if (domElements.fileProgressBar) domElements.fileProgressBar.style.width = "0%";
    if (domElements.hiddenBase64) domElements.hiddenBase64.value = "";
    if (domElements.fileMetadata) domElements.fileMetadata.value = "";
    if (domElements.downloadSection) domElements.downloadSection.style.display = "none";
    } else {
    console.error("表单元素缺失，无法重置表单");
    showToast("表单操作失败", 'error');
    }
}

// 编辑节点 - 确保不显示任何编码内容
function editNode(id, title, content) {
    try {
    const numericId = Number(id);
    if (isNaN(numericId)) {
        showToast("无效的节点ID", 'error');
        return;
    }
    
    // 先解码URI组件，再还原HTML转义字符
    const decodedTitle = htmlUnescape(decodeURIComponent(title));
    const decodedContent = htmlUnescape(decodeURIComponent(content));
    
    // 解析内容，提取文本说明和文件信息
    const parsed = parseNodeContent(decodedContent);
    
    const editIdEl = document.getElementById("edit-id");
    const nodeTitleEl = document.getElementById("node-title");
    const nodeContentEl = document.getElementById("node-content");
    const formModeTextEl = document.getElementById("form-mode-text");
    
    if (editIdEl && nodeTitleEl && nodeContentEl && formModeTextEl) {
        editingId = numericId;
        editIdEl.value = numericId;
        nodeTitleEl.value = decodedTitle;
        nodeContentEl.value = parsed.text; // 只显示文本说明
        formModeTextEl.textContent = "编辑节点";
        nodeTitleEl.focus();
        
        // 如果元数据解析有错误，给予用户提示并标记样式
        if (parsed.metadataError) {
        showToast('注意：此节点的文件信息可能已损坏，建议重新上传文件', 'warning');
        if (domElements.fileMetaInfo) {
            domElements.fileMetaInfo.className = "file-meta-info error";
        }
        // 显示数据修复提示
        if (domElements.dataRepairHint) {
            domElements.dataRepairHint.style.display = "block";
        }
        } else {
        if (domElements.fileMetaInfo) {
            domElements.fileMetaInfo.className = "file-meta-info";
        }
        if (domElements.dataRepairHint) {
            domElements.dataRepairHint.style.display = "none";
        }
        }
        
        // 如果有文件信息，加载和显示文件元数据
        if (parsed.hasFile) {
        currentFileInfo = {
            name: parsed.meta.name,
            size: parsed.meta.size,
            base64: parsed.base64,  // 后台使用但不显示
            uploadTime: parsed.meta.uploadTime,
            metadataError: parsed.metadataError
        };
        
        // 存储Base64但不显示
        if (domElements.hiddenBase64) domElements.hiddenBase64.value = parsed.base64;
        if (domElements.fileMetadata) {
            // 使用安全的JSON序列化
            domElements.fileMetadata.value = safeJsonStringify(parsed.meta);
        }
        
        // 显示文件元信息
        if (domElements.fileMetaContainer) domElements.fileMetaContainer.style.display = "block";
        if (domElements.metaFilename) domElements.metaFilename.textContent = parsed.meta.name;
        if (domElements.metaFilesize) domElements.metaFilesize.textContent = formatFileSize(parsed.meta.size);
        if (domElements.metaUploadtime) domElements.metaUploadtime.textContent = parsed.meta.uploadTime;
        if (domElements.fileInfo) domElements.fileInfo.textContent = `已选择: ${parsed.meta.name}`;
        if (domElements.downloadSection) domElements.downloadSection.style.display = "block";
        }
        
        const formSection = document.querySelector('.form-section');
        if (formSection) {
        formSection.scrollIntoView({ behavior: 'smooth' });
        }
    } else {
        throw new Error("表单元素缺失");
    }
    } catch (e) {
    showToast("编辑节点失败", 'error');
    console.error("编辑节点错误:", e);
    }
}

// 保存节点（编码内容完全在后台处理）
async function saveNode() {
    try {
    const nodeTitleEl = document.getElementById("node-title");
    const nodeContentEl = document.getElementById("node-content");
    const editIdEl = document.getElementById("edit-id");
    
    if (!nodeTitleEl || !nodeContentEl || !editIdEl) {
        throw new Error("表单元素缺失");
    }
    
    const title = nodeTitleEl.value.trim();
    const textContent = nodeContentEl.value.trim();
    const nodeId = editIdEl.value;
    
    if (!title) {
        showToast("标题不能为空", 'error');
        return;
    }

    // 构建特殊格式的内容，编码内容完全在后台处理
    let content = '';
    const hasFile = !!domElements.hiddenBase64?.value.trim();
    
    if (hasFile) {
        // 有文件时，使用特殊格式存储，包含文件元数据和Base64（用户不可见）
        // 使用安全的JSON序列化
        const safeMetadata = safeJsonStringify(JSON.parse(domElements.fileMetadata.value || '{}'));
        content = `FILE_METADATA:\n---\n${safeMetadata}\n---\n${domElements.hiddenBase64.value}\n---\n${textContent}`;
    } else {
        // 没有文件时，直接存储文本内容
        content = textContent;
    }

    if (nodeId) {
        const numericId = Number(nodeId);
        if (isNaN(numericId)) {
        throw new Error("无效的节点ID");
        }
        
        await request("/update_note", { 
        id: numericId, 
        pid: currentPid, 
        title, 
        content 
        });
        showToast('节点已更新', 'success');
    } else {
        await request("/add_note", { 
        pid: currentPid, 
        title, 
        content 
        });
        showToast('节点已添加', 'success');
    }
    
    resetForm();
    load(currentPid);
    } catch (e) {
    showToast(`${nodeId ? '更新' : '添加'}失败: ${e.message}`, 'error');
    console.error("保存节点错误:", e);
    }
}

// 检查并显示删除模态框
async function checkAndShowDeleteModal(event, id, title, hasFile) {
    // 防止事件冒泡和默认行为
    if (event) {
    event.stopPropagation();
    event.preventDefault();
    }
    
    // 显示文件提示
    if (domElements.deleteFileHint) {
    domElements.deleteFileHint.style.display = hasFile ? "block" : "none";
    }
    
    // 验证必要参数
    if (!title || title.trim() === "") {
    showToast("删除失败：节点信息不完整", 'error');
    console.error("删除失败：标题为空或未定义");
    resetDeleteButton(event, id);
    return;
    }
    
    const numericId = Number(id);
    if (isNaN(numericId)) {
    showToast("无效的节点ID", 'error');
    resetDeleteButton(event, id);
    return;
    }
    
    // 检查DOM元素是否已初始化
    if (!domElements.deleteModal) {
    initDomElements(); // 重新尝试初始化
    }
    
    // 再次检查关键元素
    if (!domElements.deleteModal || !domElements.deleteMessage || !domElements.deleteNodeTitle) {
    showToast("删除功能初始化失败，请刷新页面重试", 'error');
    console.error("删除确认框关键元素缺失");
    resetDeleteButton(event, id);
    return;
    }
    
    // 获取并禁用删除按钮
    let deleteButton = getDeleteButton(event, numericId);
    if (deleteButton) {
    deleteButton.disabled = true;
    deleteButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 检查中';
    }
    
    try {
    // 检查是否有子节点
    const childrenExist = await hasChildren(numericId);
    
    if (childrenExist) {
        // 有子节点，不允许删除
        showToast("该节点包含子节点，无法删除", 'error');
    } else {
        // 没有子节点，可以删除，显示确认框
        deletingId = numericId;
        domElements.deleteNodeTitle.textContent = title;
        domElements.deleteMessage.textContent = "确定删除以下节点吗？";
        domElements.deleteModal.classList.add("show");
    }
    } catch (e) {
    showToast(`删除操作失败: ${e.message}`, 'error');
    console.error("删除检查错误:", e);
    } finally {
    // 恢复按钮状态
    resetDeleteButton(event, numericId);
    }
}

// 辅助函数：获取删除按钮
function getDeleteButton(event, nodeId) {
    if (event && event.currentTarget) {
    return event.currentTarget;
    }
    return document.getElementById(`delete-btn-${nodeId}`);
}

// 辅助函数：重置删除按钮状态
function resetDeleteButton(event, nodeId) {
    const deleteButton = getDeleteButton(event, nodeId);
    if (deleteButton && typeof deleteButton.disabled !== 'undefined') {
    deleteButton.disabled = false;
    deleteButton.innerHTML = '<i class="fas fa-trash"></i> 删除';
    }
}

// 确认删除
async function confirmDelete() {
    if (deletingId === null) return;
    
    // 确保模态框元素存在
    if (!domElements.deleteModal) {
    showToast("删除功能异常，请刷新页面重试", 'error');
    return;
    }
    
    try {
    await request("/delete_note", { id: deletingId });
    domElements.deleteModal.classList.remove("show");
    resetForm();
    load(currentPid);
    showToast('节点已删除', 'success');
    } catch (e) {
    showToast('删除失败', 'error');
    }
}

// 关闭删除模态框
function closeDeleteModal() {
    if (domElements.deleteModal) {
    domElements.deleteModal.classList.remove("show");
    }
}

// 处理文件上传并转换为Base64（完全在后台处理，不显示编码）
function handleFileUpload(files) {
    if (!files || files.length === 0) return;
    
    const file = files[0];
    currentFileInfo.name = file.name;
    currentFileInfo.size = file.size;
    currentFileInfo.uploadTime = new Date().toLocaleString();
    currentFileInfo.metadataError = false;
    
    // 更新文件信息显示
    if (domElements.fileInfo) {
    domElements.fileInfo.textContent = `正在处理: ${file.name} (${formatFileSize(file.size)})`;
    }
    
    // 隐藏修复提示
    if (domElements.dataRepairHint) {
    domElements.dataRepairHint.style.display = "none";
    }
    
    // 显示进度条
    if (domElements.fileProgress) {
    domElements.fileProgress.style.display = "block";
    }
    if (domElements.fileProgressBar) {
    domElements.fileProgressBar.style.width = "0%";
    }
    
    const reader = new FileReader();
    
    // 进度更新
    reader.onprogress = function(e) {
    if (e.lengthComputable && domElements.fileProgressBar) {
        const percent = (e.loaded / e.total) * 100;
        domElements.fileProgressBar.style.width = percent + "%";
    }
    };
    
    // 读取完成（编码在后台处理，不向用户展示）
    reader.onload = function(e) {
    try {
        // 提取Base64数据部分（完全在后台处理）
        const base64String = e.target.result.split(',')[1];
        currentFileInfo.base64 = base64String;
        
        // 将Base64字符串放入隐藏字段（用户不可见）
        if (domElements.hiddenBase64) {
        domElements.hiddenBase64.value = base64String;
        }
        
        // 保存文件元数据，使用安全的JSON序列化
        const metadata = {
        name: currentFileInfo.name,
        size: currentFileInfo.size,
        uploadTime: currentFileInfo.uploadTime
        };
        
        if (domElements.fileMetadata) {
        domElements.fileMetadata.value = safeJsonStringify(metadata);
        }
        
        // 更新标题（如果为空）
        const nodeTitleEl = document.getElementById("node-title");
        if (nodeTitleEl && !nodeTitleEl.value.trim()) {
        nodeTitleEl.value = file.name;
        }
        
        // 重置错误样式
        if (domElements.fileMetaInfo) {
        domElements.fileMetaInfo.className = "file-meta-info";
        }
        
        // 只显示文件元信息，不显示编码
        if (domElements.fileMetaContainer) domElements.fileMetaContainer.style.display = "block";
        if (domElements.metaFilename) domElements.metaFilename.textContent = currentFileInfo.name;
        if (domElements.metaFilesize) domElements.metaFilesize.textContent = formatFileSize(currentFileInfo.size);
        if (domElements.metaUploadtime) domElements.metaUploadtime.textContent = currentFileInfo.uploadTime;
        
        // 显示下载区域
        if (domElements.downloadSection) domElements.downloadSection.style.display = "block";
        
        // 更新状态信息
        if (domElements.fileInfo) {
        domElements.fileInfo.textContent = `已完成: ${file.name} 已上传`;
        }
        
        showToast(`文件 "${file.name}" 已上传`, 'success');
    } catch (error) {
        showToast(`文件处理失败: ${error.message}`, 'error');
        console.error("文件处理错误:", error);
    }
    };
    
    // 读取失败
    reader.onerror = function() {
    showToast("文件读取失败，请重试", 'error');
    if (domElements.fileInfo) {
        domElements.fileInfo.textContent = `读取失败: ${file.name}`;
    }
    };
    
    // 读取文件并转换为DataURL（包含Base64，完全在后台处理）
    reader.readAsDataURL(file);
}

// 移除已上传的文件
function removeFile() {
    currentFileInfo = { name: "", size: 0, base64: "", uploadTime: "", metadataError: false };
    
    if (domElements.fileUpload) domElements.fileUpload.value = "";
    if (domElements.fileInfo) domElements.fileInfo.textContent = "未选择文件";
    if (domElements.fileMetaContainer) domElements.fileMetaContainer.style.display = "none";
    if (domElements.fileMetaInfo) {
    domElements.fileMetaInfo.className = "file-meta-info"; // 重置样式
    }
    if (domElements.dataRepairHint) domElements.dataRepairHint.style.display = "none";
    if (domElements.fileProgress) domElements.fileProgress.style.display = "none";
    if (domElements.fileProgressBar) domElements.fileProgressBar.style.width = "0%";
    if (domElements.hiddenBase64) domElements.hiddenBase64.value = "";
    if (domElements.fileMetadata) domElements.fileMetadata.value = "";
    if (domElements.downloadSection) domElements.downloadSection.style.display = "none";
    
    showToast("文件已移除", 'info');
}

// 将Base64内容解码并下载为文件（完全在后台处理解码）
function decodeAndDownload(nodeId, fileName, isEditing = false) {
    let base64String, name, metadataError = false;
    
    // 判断是从列表下载还是编辑模式下载
    if (isEditing) {
    // 编辑模式，使用当前表单中的文件数据（后台处理）
    base64String = domElements.hiddenBase64?.value.trim();
    name = currentFileInfo.name;
    metadataError = currentFileInfo.metadataError;
    } else if (nodeId !== null && nodeId !== undefined) {
    // 列表模式，使用缓存的文件数据（后台处理）
    const fileData = nodeFileCache[nodeId];
    if (!fileData) {
        showToast("文件数据不存在或已过期", 'error');
        return;
    }
    base64String = fileData.base64;
    name = fileName || fileData.name;
    metadataError = fileData.metadataError;
    } else {
    showToast("无法确定下载来源", 'error');
    return;
    }
    
    if (!base64String) {
    showToast("没有可解码的文件数据", 'error');
    return;
    }
    
    if (!name) {
    showToast("文件信息缺失，无法下载", 'error');
    return;
    }
    
    // 如果元数据有错误，提前警告用户
    if (metadataError) {
    if (!confirm('此文件的元数据可能已损坏，下载的文件可能无法正常使用。是否继续？')) {
        return;
    }
    }
    
    try {
    // 检查是否是有效的Base64（后台处理）
    if (!isBase64(base64String)) {
        throw new Error("文件数据损坏，无法下载");
    }
    
    // 解码Base64（完全在后台处理，用户不可见）
    const byteCharacters = atob(base64String);
    const byteNumbers = new Array(byteCharacters.length);
    
    for (let i = 0; i < byteCharacters.length; i++) {
        byteNumbers[i] = byteCharacters.charCodeAt(i);
    }
    
    const byteArray = new Uint8Array(byteNumbers);
    const blob = new Blob([byteArray], { type: 'application/octet-stream' });
    
    // 创建下载链接
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = name;
    document.body.appendChild(a);
    a.click();
    
    // 清理
    setTimeout(() => {
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
    }, 0);
    
    showToast(`文件 "${name}" 已下载`, 'success');
    } catch (error) {
    showToast(`下载失败: ${error.message}`, 'error');
    console.error("文件下载错误:", error);
    }
}

// 检查字符串是否为有效的Base64（后台处理）
function isBase64(str) {
    try {
    return btoa(atob(str)) === str;
    } catch (err) {
    return false;
    }
}

// 格式化文件大小显示
function formatFileSize(bytes) {
    if (bytes === 0) return '0 Bytes';
    const k = 1024;
    const sizes = ['Bytes', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}

// 添加拖拽文件支持
function initDragAndDrop() {
    const uploadArea = document.querySelector('.file-upload-area');
    if (!uploadArea) return;
    
    uploadArea.addEventListener('dragover', (e) => {
    e.preventDefault();
    uploadArea.style.borderColor = '#888';
    uploadArea.style.backgroundColor = '#f0f0f0';
    });
    
    uploadArea.addEventListener('dragleave', () => {
    uploadArea.style.borderColor = '#ccc';
    uploadArea.style.backgroundColor = 'transparent';
    });
    
    uploadArea.addEventListener('drop', (e) => {
    e.preventDefault();
    uploadArea.style.borderColor = '#ccc';
    uploadArea.style.backgroundColor = 'transparent';
    
    if (e.dataTransfer.files.length) {
        handleFileUpload(e.dataTransfer.files);
    }
    });
}

// 初始化
document.addEventListener('DOMContentLoaded', () => {
    // 页面加载时初始化DOM元素引用
    initDomElements();
    initDragAndDrop();
    load();
    showToast('系统就绪', 'success');
    
    // 键盘事件
    document.addEventListener('keydown', e => {
    if (e.ctrlKey && e.key === 'n') {
        e.preventDefault();
        resetForm();
    } else if (e.ctrlKey && e.key === 's') {
        e.preventDefault();
        saveNode();
    } else if (e.ctrlKey && e.key === 'b') {
        e.preventDefault();
        goBack();
    } else if (e.key === 'Escape') {
        closeDeleteModal();
    }
    });
});